package com.cskaoyan.javase.oop1._12block._2building;

/**
 * 构造代码块
 * 定义在类中成员位置,使用{}声明的代码块,称之为构造代码块
 * 作用: 随着构造器的执行而执行,它的主要作用也是给成员变量赋值用的.
 *
 * 总结一下,目前为止,学习的在创建对象过程中,为成员变量赋值的方式有:
 *      1.默认初始化,具有默认值
 *      2.显式赋值
 *      3.构造器
 *      4.构造代码块
 * 我们之前说过一个"掐头去尾",第一步执行的永远是默认初始化,最后一步执行的永远是构造器
 * 所以这里我们主要研究构造代码块和显式赋值,谁先谁后?
 *
 * 我们通过代码测试,发现:
 * 构造代码块赋值和显式赋值,谁在代码书写顺序的下面,谁就后执行.换句话说,显式赋值和构造代码块赋值,是按照代码的书写顺序从上到下执行的.
 *
 * 当然,在实际开发中,把构造代码块写在成员变量声明的上面,虽然语法允许,但是看起来比较奇怪,所以尽量不要这么做.尽量把构造代码块赋值写在成员变量声明的下面.
 *
 * 通过查看反编译文件,编译后的代码中是不存在构造代码块的结构的的,编译器会在编译代码时,将构造代码块中的代码"智能"的放入每一个构造器的前几行.
 * 之所以每一个构造器都放,是为了保证构造代码块在任何时候new对象都会被执行.
 * 所谓"智能"指的是: 保证显式赋值和构造代码块代码会按照代码的书写顺序,从上到下执行.
 * 放在前几行代码,是为了在构造器的赋值之前进行赋值.
 *
 * 正是因为构造代码块中的代码,正常情况下,会放入每一个构造器的前几行,所以我们可以把每次new创建对象都需要做的事情,
 * 提取公因式,放进构造代码块中去.
 * 所以构造器的主要用途就在这里.
 *
 * @since 09:43
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Phone p = new Phone("小米", 5000, "MIUI");
        System.out.println(p.brand);
        System.out.println(p.price);
        System.out.println(p.os);

        System.out.println("-------------------");
        Phone p2 = new Phone();
        System.out.println(p2.brand);
        System.out.println(p2.price);
        System.out.println(p2.os);
    }
}

class Phone {

    // 静态成员变量
    static int age;

    // 构造代码块赋值
    {
        brand = "苹果";
        price = 7000;
        os = "iOS";
        System.out.println("你创建了一个手机对象");

        /*
            静态的成员变量能不能使用构造代码块赋值?
            是可以的,因为new对象时,一定类加载了,静态成员变量一定已经存在了
            但是虽然可以,一般情况下,这么做好不好?
            不好,静态成员不依赖于对象,那么这么做让它的赋值依赖于创建对象,不是常规做法.
            所以我们需要一种在类加载时,执行的代码块,来完成静态成员变量的赋值
            这就是静态代码块
         */

        Phone.age = 100;
    }

    // 显式赋值
    String brand = "华为";
    double price = 6000;
    String os = "鸿蒙OS";




    public void playGame() {
        System.out.println("来把王者荣耀,开个黑!");
    }

    public void call() {
        System.out.println("打电话!");
    }

    public Phone() {
    }

    public Phone(String brand, double price, String os) {
        this.brand = brand;
        this.price = price;
        this.os = os;

    }
}